import { applyDecorators, Type } from "@nestjs/common";
import { ApiExtraModels, ApiOkResponse, getSchemaPath } from "@nestjs/swagger";

import { BaseSuccessResponseVO } from "../vo/base-response.vo";

// 定义 data 字段的描述类型
type DataDescriptor =
    | Type<any> // 单个对象，如 UserVo
    | { type: "array"; items: Type<any> } // 对象数组，如 { type: 'array', items: UserVo }
    | { type: "array"; items: { type: string } } // 基本类型数组，如 { type: 'array', items: { type: 'string' } }
    | { type: string } // 基本类型，如 { type: 'string' }
    | "string"
    | "number"
    | "boolean"
    | "object"; // 简写形式

/**
 * 创建API基础响应装饰器（注解）
 * 该函数用于生成一个装饰器，用于定义API成功响应的数据结构
 * 响应结构包含基础响应字段和具体业务数据模型
 * 支持 data 为：单个对象、对象数组、基本类型、基本类型数组
 *
 * @param dataDescriptor - data 字段的类型描述
 * @example
 *   ApiBaseResponse(UserVo)                     // data: UserVo
 *   ApiBaseResponse({ type: 'array', items: UserVo }) // data: UserVo[]
 *   ApiBaseResponse('string')                   // data: string
 *   ApiBaseResponse({ type: 'array', items: { type: 'string' } }) // data: string[]
 */
export const ApiBaseResponse = (dataDescriptor: DataDescriptor) => {
    // 解析 data 的 schema
    const dataSchema = buildDataSchema(dataDescriptor);

    // 如果 data 是对象或对象数组，需要注册额外模型
    const extraModels: Type<any>[] = [];
    if (typeof dataDescriptor === "function") {
        // 单个对象
        extraModels.push(dataDescriptor);
    } else if (typeof dataDescriptor === "object" && "items" in dataDescriptor) {
        const items = dataDescriptor.items;
        if (typeof items === "function") {
            // 对象数组
            extraModels.push(items);
        }
    }
    // 应用多个装饰器来定义API响应结构
    return applyDecorators(
        // 注册额外模型, 确保 BaseSuccessResponseVO 和业务模型都能在 API 文档中正确显示（仅当涉及 class 时）
        ...(extraModels.length > 0
            ? [ApiExtraModels(BaseSuccessResponseVO, ...extraModels)]
            : [ApiExtraModels(BaseSuccessResponseVO)]),
        // 定义200状态码的响应结构
        ApiOkResponse({
            schema: {
                // 使用allOf组合多个模式定义
                allOf: [
                    // 引用基础响应模型的模式定义
                    { $ref: getSchemaPath(BaseSuccessResponseVO) },
                    // 定义包含业务数据的属性结构
                    {
                        properties: {
                            data: dataSchema
                        }
                    }
                ]
            }
        })
    );
};

// 辅助函数：根据描述构建 data 的 schema
function buildDataSchema(descriptor: DataDescriptor): any {
    if (typeof descriptor === "function") {
        // 单个对象，如 UserVo
        return { $ref: getSchemaPath(descriptor) };
    }

    if (typeof descriptor === "string") {
        // 基本类型简写：'string', 'number' 等
        return { type: descriptor };
    }

    if (typeof descriptor === "object") {
        if ("type" in descriptor && descriptor.type === "array") {
            if (!("items" in descriptor)) throw new Error("Array type must have 'items' property");
            // 数组类型
            const items = descriptor.items;
            if (typeof items === "function") {
                // 对象数组
                return {
                    type: "array",
                    items: { $ref: getSchemaPath(items) }
                };
            } else if (typeof items === "object" && "type" in items) {
                // 基本类型数组
                return {
                    type: "array",
                    items: { type: items.type }
                };
            }
        } else if ("type" in descriptor) {
            // 基本类型对象形式：{ type: 'string' }
            return { type: descriptor.type };
        }
    }

    throw new Error(`Unsupported data descriptor: ${JSON.stringify(descriptor)}`);
}
